module CameraConfig (
  // Host Side
  iClk,
  iRstN,
  // I2C Side
  oSclk,
  ioSda
);

// Host Side
input iClk;
input iRstN;
// I2C Side
output oSclk;
inout ioSda;

// ------------------------- Paramemters ----------------------------
// Clock Setting
parameter CLK_FREQ = 50000000; // 50 MHz
parameter I2C_FREQ = 20000;  // 20 KHz
// LUT Data Number
parameter LUT_SIZE = 10;
// CAM Data Index
parameter DUMMY_DATA = 0;
parameter PROGRESSIVE_SCAN = 1;
parameter RGB_IMAGE_PLANE = 2;
parameter WINDOW_SIZING_HS = 3;
parameter WINDOW_SIZING_HE = 4;
parameter MANUAL_ADJUST_MODE_EN = 5;
parameter GAIN_SETTINGS = 6;
parameter EXPTIME_SETTING = 7;
parameter TRI_STATED_BUSES = 8;
parameter CLOCK_RATE_CONTROL = 9;

// ------------------------- Internal Registers/Wires ----------------
reg [15:0] clockDivide = 0;
reg [23:0] i2cData = 0;
reg controllClock = 0;
reg startSend = 0;
wire endSend;
wire i2cAck;
reg [15:0] lutData = 0;
reg [5:0] lutIndex = 0;
reg [3:0] state = 0;

// ------------------------- always blocks  --------------------------
///////////////////// I2C Control Clock ////////////////////////
always@(posedge iClk or negedge iRstN)
begin
  if(!iRstN) begin
    controllClock <= 0;
    clockDivide <= 0;
  end
  else begin
    if(clockDivide < (CLK_FREQ/I2C_FREQ)) begin
      clockDivide <= clockDivide + 1'b1;
    end
    else begin
      clockDivide <= 0;
      controllClock <= ~controllClock;
    end
  end
end

////////////////////// Config Control ////////////////////////////
always@(posedge controllClock or negedge iRstN) begin
  if(!iRstN) begin
    lutIndex <= 0;
    state <= 0;
    startSend <= 0;
  end
  else
  begin
    if(lutIndex < LUT_SIZE) begin
      case(state)
        0: begin
          i2cData <= {8'h42, lutData};
          startSend <= 1;
          state <= 1;
        end
        1: begin
          if(endSend) begin
            if(!i2cAck) begin
              state <= 2;
            end
            else begin
              state <= 0;
            end
            startSend <= 0;
          end
        end
        2: begin
          lutIndex <= lutIndex+1'b1;
          state <= 0;
        end
      endcase
    end
  end
end

///////////////////// Config Data LUT   ////////////////////////// 
always
begin
 case(lutIndex)
  // CAM Config Data
  DUMMY_DATA            : lutData <= 16'h0000;
  PROGRESSIVE_SCAN      : lutData <= 16'h2824;
  //RGB_IMAGE_PLANE     : lutData <= 16'h122C; //RGB
  RGB_IMAGE_PLANE       : lutData <= 16'h1224; //YCrCb
  //WINDOW_SIZING_HS    : lutData <= 16'h174B; //83.pixeltől
  //WINDOW_SIZING_HE    : lutData <= 16'h18C3; //562. pixelig
  MANUAL_ADJUST_MODE_EN : lutData <= 16'h1300;
  GAIN_SETTINGS         : lutData <= 16'h0000;
  EXPTIME_SETTING       : lutData <= 16'h1080;
  //TRI_STATED_BUSES    : lutData <= 16'h1305;
  CLOCK_RATE_CONTROL    : lutData <= 16'h1102;
  default               : lutData <= 16'h0000;
 endcase
end

// ----------------------- internal modules ------------------------
I2C_Controller u0 (
  .CLOCK(controllClock),  // Controller Work Clock
  .I2C_SCLK(oSclk),       // I2C CLOCK
  .I2C_SDAT(ioSda),       // I2C DATA
  .I2C_DATA(i2cData),     // DATA:[SLAVE_ADDR,SUB_ADDR,DATA]
  .GO(startSend),         // GO transfor
  .END(endSend),          // END transfor 
  .ACK(i2cAck),           // ACK
  .RESET(iRstN)
);

endmodule
